/**
 * @author Luc Yriarte
 * 
 * Licence : BSD http://www.opensource.org/licenses/bsd-license.php
 *  
 */
package physicSim;

import java.awt.Component;

import basicSim.Object3D;
import basicSim.SimView;
import basicSim.Vector;


public class World extends Thread {

	/** Time step in millisec for 12 fps */
	public static int DEFAULT_MS = 83;
	/** Time step in millisec */
	public int millisec = DEFAULT_MS; 
	/** By default gravity is 10 m.s-2 */
	public static double DEFAULT_GRAVITY=10;
	/** Gravity in this world */
	public double g = DEFAULT_GRAVITY;
	public PhysicVector gravity;
	/** Objects in this world */
	protected SolidObject object[] = null;
	public int nObjects = 0;
	
	/** All solids are children of the space oject */
	public Object3D space;
	/** Current execution time in seconds */
	public double time=0;
	/** System time in milliseconds */
	public long systime;
	/** view graphics */
	public SimView simView;
	/** applet */
	public Component view;
	
	/**
	 * 
	 */
	public World() {
		super();
		this.gravity=new PhysicVector(0,-g,0);
		this.space = new Object3D();
	}

	/**
	 * @param gravity
	 */
	public World(double g) {
		super();
		this.g = g;
		this.gravity=new PhysicVector(0,-g,0);
		this.space = new Object3D();
	}
	
	/**
	 * @param millisec
	 * @param g
	 */
	public World(double g, int millisec) {
		super();
		this.millisec = millisec;
		this.g = g;
		this.gravity=new PhysicVector(0,-g,0);
		this.space = new Object3D();
}
	
	public int addObject(SolidObject obj) {
		int i;
		SolidObject[] prevObj = object;
		object = new SolidObject[nObjects + 1];
		for (i = 0; i < nObjects; i++) {
			object[i] = prevObj[i];
		}
		object[nObjects] = obj;
		space.addChild(obj.object3D);
		space.reset();
		nObjects++;
		return nObjects;
	}

	public SolidObject getObject(int i) {
		if (object == null)
			return null;
		return object[i];
	}
 
	public SimView getSimView() {
		return simView;
	}
	public void setSimView(SimView simView) {
		this.simView = simView;
		space.setDrawMode(simView.drawFacets ? Object3D.DRAW_FACETS : Object3D.DRAW_WIREFRAME);		
	}
	
	public void updateObjects(double dt) {
		int i;
//		System.out.println("Update " + nObjects + " objects time=" + time + " dt=" + dt);
		Vector dg = new Vector(gravity.mulNum(dt));
		for (i = 0; i < nObjects; i++) {
			object[i].applyForce(dg);
			object[i].updateState(dt);
		}
	}
	
	public void run() {
		double dt;
		time = 0;
		space.reset();
		while(true) {
			systime = System.currentTimeMillis();
			try {
				sleep(millisec);				
			} catch (Exception e) {
				System.out.println("runtime exception " + e.toString());
			}
			/* Calculate objects position velocity and acceleration */
			dt = (double) (System.currentTimeMillis() - systime) / 1000;
			updateObjects(dt);
			time+=dt;
			/* Redraw objects */
			simView.updateModel();
			view.repaint();
		}
	}

}
